<html>
  <head>
    <meta charset="utf-8">
    <title>Mongoose ODM</title>
    <style>
      body {
        background: url('/docs/2.7.x/images/bg.png');
        padding: 0 30px 30px;
        margin-top: 0;
      }

      #wrap {
        background: url('/docs/2.7.x/images/pattern.png') no-repeat -134px -211px;
        min-height: 600px;
        padding-top: 30px;
      }

      #page {
        width: 650px;
        margin: auto;
        position: relative;
      }

      #footer {
        font: 13px Helvetica;
        padding-top: 15px;
        border-top: 1px solid #000;
        color: #666;
        margin-top: 25px;
      }

      #footer > div {
        padding-top: 8px;
        float: right;
        text-align: right;
        padding-bottom: 20px;
      }

      #content {
        color: #111;
        font: 15px Courier;
      }

      #content h1, #content h2, #content h3 {
        text-shadow: 0 1px 0 #fff;
      }

      #announce {
        background: #2A758A;
        border: 10px solid black;
        border-radius: 7px;
        padding: 30px;
        font-size: 125%;
        color: white;
        text-shadow: none;
        font-family: Arial;
      }

      #announce a {
        color: orange;
        text-shadow: none;
      }

      pre {
        background: rgba(255,255,255,.8);
        border: 1px solid #c6c6c6;
        padding: 10px;
        border-radius: 3px;
        box-shadow: 1px 3px 6px #ddd;
      }

      code {
        background: rgba(255,255,255,.8);
        border: 1px solid #c6c6c6;
        color: #333;
        border-radius: 3px
      }

      pre code {
        border: 0 none;
      }

      form {
        font: bold 12px Helvetica;
        text-shadow: 0 1px 0 #fff;
        float: left;
        padding-bottom: 25px;
      }

      form img {
        margin-right: 5px
      }

      #google-members-count {
        vertical-align: top;
        line-height: 32px;
      }

      h1 a {
        background: url('/docs/2.7.x/images/logo.png');
        width: 404px;
        height: 47px;
        margin-bottom: 40px;
        text-indent: -500em;
        display: block;
      }

      a {
        color: #2a758a;
        text-shadow: 0 1px 0 #fff;
        text-decoration: none;
      }

      a:hover {
        opacity: 0.8;
      }

      #menu {
        position: fixed;
        top: 0;
        left: 0;
        height: 100%;
        background-color: rgba(0,0,0,0.3);
        font: bold 15px Helvetica;
        border-right: 1px solid rgba(0,0,0,0.2);
      }

      #menu ul {
        margin: 0;
        padding: 50px 0;
      }

      #menu ul li {
        list-style-type: none;
        padding-left: 15px;
        padding-right: 20px;
      }

      #menu ul li a {
        color: #fff;
        text-shadow: none;
      }
      #menu ul li a:hover {
        text-decoration: underline;
      }
      #wild { margin-top: 10px; }
    </style>

    <script>
      var _gaq = _gaq || [];
      _gaq.push(['_setAccount', 'UA-1122274-9']);
      _gaq.push(['_trackPageview']);

      (function() {
        var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
        var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
      })();
      
      function getMembers(data){
        if (!(data && data.query && data.query.results && data.query.results.p)) return;
        var members = document.createElement('span');
        members.id = 'google-members-count';
        members.innerHTML = '('+ data.query.results.p +' members)';
        document.getElementsByTagName('FORM')[0].insertBefore(members, document.getElementById('google-subscribe-input'));
      };

      window.onload = function(){
        // lame jsonp
        var script = document.createElement('script');
        script.src = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22http%3A%2F%2Fgroups.google.com%2Fgroup%2Fmongoose-orm%2Fabout%22%20and%20xpath%3D'%2F%2Fdiv%5B%40class%3D%5C'maincontbox%5C'%5D%2Ftable%2Ftr%5B1%5D%2Ftd%2Fp%5B1%5D'%0A&format=json&callback=getMembers";
        document.head.appendChild(script);
      };
    </script>
  </head>
  <body>
    <a href="http://github.com/learnboost/mongoose"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png" alt="Fork me on GitHub"></a>
    <div id="wrap">
      <div id="page">
        <div id="menu">
          <ul>
            <li><a href="../index.html">Home</a></li>
            <li><a href="model-definition.html">Models/Schemas</a></li>
            <li><a href="schematypes.html">Schema Types</a></li>
            <li><a href="schema-options.html">Schema Options</a></li>
            <li><a href="middleware.html">Middleware</a></li>
            <li><a href="finding-documents.html">Finding Docs</a></li>
            <li><a href="updating-documents.html">Updating Docs</a></li>
            <li><a href="query.html">Queries</a></li>
            <li><a href="querystream.html">Query Streams</a></li>
            <li><a href="methods-statics.html">Methods &amp; Statics</a>
            <li><a href="defaults.html">Defaults</a></li>
            <li><a href="indexes.html">Indexes</a></li>
            <li><a href="validation.html">Validation</a></li>
            <li><a href="virtuals.html">Virtuals</a></li>
            <li><a href="getters-setters.html">Getters / Setters</a></li>
            <li><a href="embedded-documents.html">Embedded Docs</a></li>
            <li><a href="populate.html">Populate (DBRef-like)</a></li>
            <li><a href="plugins.html">Plugins</a></li>
            <li><a href="errors.html">Errors</a></li>
            <li><a href="migration-1x-2x.html">v1x - v2x Migration</a></li>
            <li><a href="api.html">API</a></li>
          </ul>
        </div>

        <h1><a href="../index.html">Mongoose</a></h1>

        <div id="content">
          <!-- ANNOUNCE -->
          <h1>Schema Types</h1>

<p><code>SchemaType</code>s take care of validation, casting, defaults, and other general options in our models. We can specify our types one of two ways:</p>

<pre><code>// directly without options
var Person = new Schema({
    title   : String
});

// or with options
var Person = new Schema({
    title   : { type: String, lowercase: true }
});
</code></pre>

<p>In the example above we specified the <code>lowercase</code> option for strings which will lowercase the string whenever it is set. Options are functions that are called on each SchemaType. Each <code>SchemaType</code> has its own set of custom options.</p>

<h2>Available Schema Types</h2>

<h3>String</h3>

<ul>
<li><p><code>lowercase</code>: {Boolean}</p>

<p>Creates a setter which calls <code>.toLowerCase()</code> on the value</p></li>
<li><p><code>uppercase</code>: {Boolean}</p>

<p>Creates a setter which calls <code>.toUpperCase()</code> on the value</p></li>
<li><p><code>trim</code>: {Boolean}</p>

<p>Creates a setter which calls <code>.trim()</code> on the value</p></li>
<li><p><code>match</code>: {RegExp}</p>

<p>Creates a RegExp based <a href="validation.html">validator</a>. The value being set is <code>.test()</code>ed against the RegExp. If it does not pass, validation will fail.</p></li>
<li><p><code>enum</code>: {Array}</p>

<p>Creates an enum validator. If the value being set is not in this array, validation will fail.</p></li>
</ul>

<h3>Number</h3>

<ul>
<li><p><code>min</code>: {Number}</p>

<p>Creates a validator which checks that the value being set is not less than the value specified.</p></li>
<li><p><code>max</code>: {Number}</p>

<p>Creates a validator which checks that the value being set is not greater than the value specified.</p></li>
</ul>

<h3>Date</h3>

<ul>
<li>no custom options</li>
</ul>

<h3>Boolean</h3>

<ul>
<li>no custom options</li>
</ul>

<h3>Buffer (v2.x only)</h3>

<ul>
<li>no custom options</li>
</ul>

<h3>ObjectId</h3>

<p>To specify a type of <code>ObjectId</code>, use <code>Schema.ObjectId</code> in your declaration.</p>

<pre><code>var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var Car = new Schema({ driver: Schema.ObjectId })
</code></pre>

<ul>
<li>no custom options</li>
</ul>

<h3>Mixed</h3>

<p>An "anything goes" <code>SchemaType</code>, its flexibility comes at a trade-off of it being harder to maintain. <code>Mixed</code> is available either through <code>Schema.Types.Mixed</code> or by passing an empty object literal. The following are equivalent:</p>

<pre><code>var Any = new Schema({ any: {} });
var Any = new Schema({ any: Schema.Types.Mixed });
</code></pre>

<p>Since it is a schema-less type, you can change the value to anything else you like, but Mongoose loses the ability to auto detect/save those changes. To "tell" Mongoose that the value of a <code>Mixed</code> type has changed, call the <code>.markModified(path)</code> method of the document passing the path to the <code>Mixed</code> type you just changed.</p>

<pre><code>person.anything = { x: [3, 4, { y: "changed" }] };
person.markModified('anything');
person.save(); // anything will now get saved
</code></pre>

<ul>
<li>no custom options</li>
</ul>

<h3>Array</h3>

<p>Creates an array of <code>SchemaTypes</code> or <a href="embedded-documents.html">Embedded Documents</a>.</p>

<pre><code>var ToySchema = new Schema({ name: String });
var ToyBox = new Schema({
    toys: [ToySchema]
  , buffers: [Buffer]
  , string:  [String]
  , numbers: [Number]
  ... etc
});
</code></pre>

<p>Note: specifying an empty array is equivalent to <code>[Mixed]</code>. The following all create arrays of <code>Mixed</code>:</p>

<pre><code>var Empty1 = new Schema({ any: [] });
var Empty2 = new Schema({ any: Array });
var Empty3 = new Schema({ any: [Schema.Types.Mixed] });
var Empty4 = new Schema({ any: [{}] });
</code></pre>

<ul>
<li>no custom options</li>
</ul>

<h2>Additional options</h2>

<p>Besides the options listed above, all SchemaTypes share the following additional options.</p>

<ul>
<li><p><code>default</code>: {Function|value} - Determines the default value for the path. All values are casted. If using a function, the value it returns will be casted as the default value.</p></li>
<li><p><code>required</code>: {Boolean} - If true, creates a validation rule requiring this path be set before saving occurs.</p></li>
<li><p><code>select</code>: {Boolean} - Specifies default path selection behavior. In other words, you can specify if this path should be included or excluded from query results by default.</p>

<pre><code>// Excluding `bio` from query results by default


var Person = new Schema({ bio: { type: String, select: false }})
var P = db.model('Person', Person);
P.findOne(function (err, p) {
  console.log(p.bio) // undefined
});


// Including `name` in query results by default


var Person = new Schema({
    name: { type: String, select: true }
  , age: Number
})


var P = db.model('Person', Person);
P.findOne().select('age').exec(function (err, p) {
  console.log(p.isSelected('age'))  // true
  console.log(p.isSelected('name')) // true
});


// can also be overridden on a query by query basis


var Person = new Schema({ bio: { type: String, select: false }})
var P = db.model('Person', Person);
P.findOne().select('bio').exec(callback); // bio will be selected
</code></pre></li>
<li><p><code>get</code>: {Function} - Adds a getter for this path. See the <a href="getters-setters.html">getters / setters</a> docs for more detail.</p></li>
<li><p><code>set</code>: {Function} - Adds a setter for this path. See the <a href="getters-setters.html">getters / setters</a> docs for more detail.</p></li>
<li><p><code>index</code>: {Boolean|Object} - Tells Mongoose to ensure an index is created for this path. An object can be passed as well.</p>

<pre><code>var Person = new Schema({ name: { type: String, index: true }})


var name = { type: String, index: { unique: true }}
var Person = new Schema({ name: name })
</code></pre>

<p>Note: if the index already exists on the db, it will <em>not</em> be replaced.</p></li>
<li><p><code>unique</code>: {Boolean} - Tells Mongoose to ensure a unique index is created for this path. The following are equivalent:</p>

<pre><code>var Person = new Schema({ name: { type: String, unique: true }})


var name = { type: String, index: { unique: true }}
var Person = new Schema({ name: name })
</code></pre>

<p>Note: if the index already exists on the db, it will <em>not</em> be replaced.</p></li>
<li><p><code>sparse</code>: {Boolean} - Tells Mongoose to ensure a sparse index is created for this path. The following are equivalent:</p>

<pre><code>var Person = new Schema({ name: { type: String, sparse: true }})


var name = { type: String, index: { sparse: true }}
var Person = new Schema({ name: name })
</code></pre>

<p>Note: if the index already exists on the db, it will <em>not</em> be replaced.</p></li>
<li><p><code>validate</code>: {Function|RegExp|Array} - Creates a <a href="validation.html">validator</a> for this path.</p>

<pre><code>// passing a function
function hasNumber (v) {
  return v.length &amp;&amp; /\d/.test(v);
}
var street = { type: String, validate: hasNumber }
var Person = new Schema({ street: street });


// passing a RegExp
var street = { type: String, validate: /\d/ }
var Person = new Schema({ street: street });


// passing an array
var street = {
    type: String
  , validate: [hasNumber, 'street number required']
}
var Person = new Schema({ street: street })


// or
var street = {
    type: String
  , validate: [/\d/, 'street number required']
}
var Person = new Schema({ street: street });
</code></pre>

<p>For more detail about validation including async validation, see the <a href="validation.html">validation</a> page.</p></li>
</ul>

<h2>Alternate options definition</h2>

<p>Instead of defining options when instanciating your <code>Schema</code> we can also access keys through the <code>path</code> function and add options there:</p>

<pre><code>Person.path('age').max(400);

Person.path('meta.birth').set(function (v) {
  // this is a setter
});

Person.path('title').validate(function (v) {
  return v.length &gt; 50;
});
</code></pre>
        </div>

        <div id="footer">

          <form action="http://groups.google.com/group/mongoose-orm/boxsubscribe">
           <a href="http://groups.google.com/group/mongoose-orm" id="google-subscribe-link"><img src="/docs/2.7.x/images/groups.png" border="0"></a>
           <span id="google-members-count">&nbsp;</span>
           <div id="google-subscribe-input">
             Email: <input type="text" name="email" id="google-subscribe-email">
             <input type="submit" name="go" value="Subscribe">
           </div>
          </form>

          <div>
            Mongoose by <a href="http://github.com/learnboost">LearnBoost Labs</a>.<br>
            Released under the MIT license.<br>
            Copyright <a href="http://learnboost.com">LearnBoost 2011</a>.
          </div>
        </div>
      </div>
    </div>
  </body>
</html>
